package sms

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"net/url"
	"strings"
)

const CN = "https://sms.yunpian.com/v2/sms/single_send.json"
const USA = "https://us.yunpian.com/v2/sms/single_send.json"

type Yunpian struct {
	ApiKey      string
	DefaultText string
}

// 注册到统一的注册配置
func init() {
	config["yuanpian"] = func() SMS {
		return &Yunpian{ApiKey: "62d12d04da4c8d91d2cf72b27332584b", DefaultText: "【OKIN】Verification code: #{code}, will be valid for 10 minutes."}
	}
}

// SendTplMessage 发送短信模板
func (yuanpian *Yunpian) SendTplMessage(phone, tplId string, tplValue map[string]string) error {

	// 重新赋值url和手机号
	apiUrl, mobile := yuanpian.getUrlAndPhone(phone)
	// 组装
	valueString := yuanpian.getTplValueString(tplValue)

	// body
	body := url.Values{
		"tpl_id":    {tplId},
		"tpl_value": {valueString},
		"apikey":    {yuanpian.ApiKey},
		"mobile":    {mobile},
	}.Encode()

	// 返回结果
	return yuanpian.Request(apiUrl, bytes.NewBufferString(body))

}

// SendSMSCode 发送短信验证码
func (yuanpian *Yunpian) SendSMSCode(phone, code string) error {

	// 重新赋值url和手机号
	apiUrl, mobile := yuanpian.getUrlAndPhone(phone)
	text := strings.ReplaceAll(yuanpian.ApiKey, "#{code}", code)

	// body
	body := url.Values{
		"text":   {text},
		"apikey": {yuanpian.ApiKey},
		"mobile": {mobile},
	}.Encode()

	// 返回结果
	return yuanpian.Request(apiUrl, bytes.NewBufferString(body))
}

// SendTplMessage 发送短信模板
func (yuanpian *Yunpian) getTplValueString(tplValue map[string]string) string {

	values := url.Values{}

	for key, value := range tplValue {
		key = url.QueryEscape("#" + key + "#")
		value = url.QueryEscape(value)
		values.Add(key, value)
	}

	return values.Encode()
}

// SendTplMessage 发送短信模板
func (yuanpian *Yunpian) getUrlAndPhone(phone string) (apiUrl string, newPhone string) {

	apiUrl = USA
	newPhone = phone

	if IsChinaPhone(phone) {
		apiUrl = CN
		newPhone = phone[3:]
	}

	return
}

// Request 发送请求
func (yuanpian *Yunpian) Request(apiUrl string, body io.Reader) error {
	request, err := http.NewRequest(http.MethodPost, apiUrl, body)
	if err != nil {
		return err
	}
	// 请求头
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("Accept", "text/plain;charset=utf-8")
	request.Header.Set("charset", "utf-8")

	// 发送请求
	resp, err := http.DefaultClient.Do(request)
	if err != nil {
		return err
	}

	// 返回结果
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	res := make(map[string]interface{})
	err = json.Unmarshal(data, &res)
	if err != nil {
		return err
	}

	if res["code"].(float64) != 0 {
		return errors.New(string(data))
	}

	return nil
}
